package cn.tedu.submarine;
import javax.swing.*;
import java.awt.*;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Random;
import java.util.Arrays;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

//整个游戏世界
public class World  extends JPanel {
    public static final int WIDTH = 641;
    public static final int HEIGHT = 479;

    public static final int START = 0;
    public static final int RUNNING = 1;
    public static final int GAME_OVER = 2;
    private int state = START;


    private Battleship ship = new Battleship();//战舰对象
    private SeaObject[] submarines = {

    };//潜艇对象数组
    private SeaObject[] thunders = {

    };//雷的数组
    private Bomb[] bombs = {

    };//深水炸弹数组

    public SeaObject nextSubmarine() {
        Random rand = new Random();//随机数对象
        int type = rand.nextInt(20);
        if (type<10){
            return new ObserveSubmarine();
        }else if(type<15){
            return new TorpedoSubmarine();
        }else {
            return new MineSubmarine();
        }
    }

    private int subEnterIndex = 0;
    public void submarinesEnterAction(){//潜艇入场
        subEnterIndex++;
        if (subEnterIndex%40==0){
            SeaObject obj = nextSubmarine();//
            submarines = Arrays.copyOf(submarines,
                    submarines.length+1);
            submarines[submarines.length-1]=obj;
        }

    }
    private int thunEnterIndex = 0;
    public void thundersEnterAction(){
        thunEnterIndex++;
        if (thunEnterIndex%100==0){
            for (int i = 0;i<submarines.length;i++){
                SeaObject obj = submarines[i].shootThunder();
                if (obj!=null){
                    thunders = Arrays.copyOf(thunders,thunders.length+1);
                    thunders[thunders.length-1] = obj;
                }
            }
        }
    }
    public void stepAction(){
        for (int i=0;i<submarines.length;i++){
            submarines[i].step();
        }
        for (int i=0;i<thunders.length;i++){
            thunders[i].step();
        }
        for (int i=0;i<bombs.length;i++){
            bombs[i].step();
        }
    }
    public void bombEnterAction(){
        Bomb obj = ship.shootBomb();//获取深水炸弹对象
        bombs = Arrays.copyOf(bombs,bombs.length+1);
        bombs[bombs.length-1] = obj;
    }
    public void outOfBoundsAction(){//
        for (int i=0;i<submarines.length;i++){//编译所有潜艇
            if (submarines[i].isOutOfBounds()||submarines[i].isDead()){//越界了
                submarines[i]=submarines[submarines.length-1];//将越界潜艇替换
                submarines = Arrays.copyOf(submarines,submarines.length-1);//缩容数组
            }
        }
        for (int i=0;i<thunders.length;i++){
            if (thunders[i].isOutOfBounds()||thunders[i].isDead()){
                thunders[i]=thunders[thunders.length-1];
                thunders= Arrays.copyOf(thunders,thunders.length-1);
            }
        }
        for (int i=0;i<bombs.length;i++) {
            if (bombs[i].isOutOfBounds()||bombs[i].isDead()) {
                bombs[i] = bombs[bombs.length - 1];
                bombs = Arrays.copyOf(bombs, bombs.length - 1);
            }
        }
    }
    private  int score = 0;
    public void bombBangAction(){
        for (int i=0;i<bombs.length;i++){
            Bomb b = bombs[i];
            for (int j=0;j<submarines.length;j++){
                SeaObject s = submarines[j];
                if (b.isLive() && s.isLive() && s.isHit(b)){
                    s.goDead();
                    b.goDead();

                    if (s instanceof EnemyScore){
                        EnemyScore es =(EnemyScore)s;
                        score+=es.getScore();
                    }
                    if (s instanceof EnemyLife){
                        EnemyLife el = (EnemyLife)s;
                        int life = el.getLife();
                        ship.addLife(life);
                    }
                }
            }
        }
    }
    public void thunderBangAction(){
        for (int i=0;i<thunders.length;i++){
            SeaObject t = thunders[i];
            if (t.isLive() && ship.isLive() && ship.isHit(t)){
                t.goDead();
                ship.subtractLife();
            }
        }
    }
    public void checkGameOverAction(){
        if (ship.getLife()<=0){
            state=GAME_OVER;
        }
    }
    public void action() {
        KeyAdapter k = new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode()==KeyEvent.VK_SPACE){//按下空格键
                    switch (state){//
                        case START:
                            state=RUNNING;
                            break;
                        case RUNNING:
                            bombEnterAction();//深水炸弹入场
                            break;
                        case GAME_OVER:
                            score =0;
                            ship = new Battleship();
                            submarines = new SeaObject[0];
                            thunders = new SeaObject[0];
                            bombs = new Bomb[0];
                            state=START;
                            break;
                    }
                }
                if (e.getKeyCode()==KeyEvent.VK_LEFT){//左键
                    ship.moveLeft();
                }
                if (e.getKeyCode()==KeyEvent.VK_RIGHT){//右键
                    ship.moveRight();
                }
            }
        };
        this.addKeyListener(k);//添加键盘侦听器


        Timer timer = new Timer();//定时器对象
        int interval = 10;//定时间隔（以毫秒为单位）
        timer.schedule(new TimerTask() {
            public void run() {
                if (state==RUNNING) {//仅在运行转态时执行
                    submarinesEnterAction();//潜艇入场
                    thundersEnterAction();//雷入场
                    stepAction();//对象移动
                    outOfBoundsAction();//删除越界的海洋对象
                    bombBangAction();//深水炸弹与潜艇的碰撞
                    thunderBangAction();//雷与战舰的碰撞
                    checkGameOverAction();//检测游戏结束
                }
                repaint();//重画（重新调用paint()方法）

            }
        },interval,interval);

    }

    //画窗口
    public void paintWorld() {
        JFrame frame = new JFrame();
        this.setFocusable(true);
        frame.add(this);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(WIDTH + 16, HEIGHT + 39);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    public void paint(Graphics g){
        switch (state){
            case START:
                Images.start.paintIcon(null,g,0,0);
                break;
            case GAME_OVER:
                Images.gameover.paintIcon(null,g,0,0);
                break;
            case RUNNING:
                Images.sea.paintIcon(null,g,0,0);
                ship.paintImage(g);
                for (int i=0;i<submarines.length;i++){
                    submarines[i].paintImage(g);
                }
                for (int i=0;i<thunders.length;i++){
                    thunders[i].paintImage(g);
                }
                for (int i=0;i<bombs.length;i++){
                    bombs[i].paintImage(g);
                }
                g.drawString("SCORE"+score,200,50);
                g.drawString("LIFE"+ship.getLife(),400,50);
        }

    }

    public static void main(String[] args) {
        World w = new World();
        w.paintWorld();
        w.action();

    }

}



/*
1.问题：为何要将那一堆引用设计在main的外面？
        答:若将引用设计在main中，意味着引用只能在main中使用
        而world类中后期会设计很多很多的方法，都需要用到那一堆引用，
        所以设计在main的外面，以此来扩大作用范围
        2.为什么要单独创建一个action()方法来测试？
        答:因为main方法是static的，而在static的方法中是无法访问的那一顿引用的
        所以单独创建一个非static方法action()方法来测试
        ------static内容 第五天详细讲
        3.为什么要先创建World对象，再调用action()方法？
        答:因为main方法是static的，在static方法中不能直接调用非static的方法
        所以先创建当前World类对象，再调用action()方法


 */